package org.iori.pdf;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.HashMap;
import java.util.ListIterator;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfObject;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;

import com.itextpdf.text.pdf.PdfArray;

public class PdfChecker {
    public static void main( String[] args ) throws IOException {
    	String[] argss = new String[]{
//    			"/Users/xing_lun/work/pdfcheck/59399_18190_1200.jpg.pdf",
//    			"/Users/xing_lun/work/pdfcheck/64561_4500_72.pdf",
//    			"/Users/xing_lun/work/pdfcheck/founder.pdf",
//    			"/Users/xing_lun/work/pdfcheck/C-BOX.pdf"
    			"/Users/xing_lun/work/pdfcheck/y1.pdf"
    			};

		for (int i = 0; i < argss.length; i++ ) {
		    check( argss[i], argss.length );
		    System.out.println();
		}
    }

    public static void check( String filename, int argc ) throws IOException {
    	PdfReader pdf = null;
    	try {
    		pdf = new PdfReader( filename );
    	} catch (IOException e) {
            e.printStackTrace();
            output( filename, "PDF文書は破損しており、修復が必要");
            return;
        }

		if ( argc == 1 ) {
		    output( null, "filename", filename );
		    filename = null;
		}
		
		float fileSize = getFileSizes(pdf);

		output( filename, "fileSize(MB)", fileSize);
		output( filename, "version", pdf.getPdfVersion() );
		output( filename, "encryption", pdf.isEncrypted() );
		if ( pdf.isEncrypted() ) {
		    int permission = pdf.getPermissions();
		    output( filename, "permission: allow print", ( ( permission & PdfWriter.ALLOW_PRINTING ) == PdfWriter.ALLOW_PRINTING ) );
		    output( filename, "permission: allow modify", ( ( permission & PdfWriter.ALLOW_MODIFY_CONTENTS ) == PdfWriter.ALLOW_MODIFY_CONTENTS ) );
		    output( filename, "permission: allow assembly", ( ( permission & PdfWriter.ALLOW_ASSEMBLY ) == PdfWriter.ALLOW_ASSEMBLY ) );
		    output( filename, "permission: allow copy", ( ( permission & PdfWriter.ALLOW_COPY ) == PdfWriter.ALLOW_COPY ) );
		    output( filename, "permission: allow screenreader", ( ( permission & PdfWriter.ALLOW_SCREENREADERS ) == PdfWriter.ALLOW_SCREENREADERS ) );
		}
		
		
		HashMap map = pdf.getInfo();
		Iterator ite = map.keySet().iterator();
		while( ite.hasNext() ) {
		    String prop = (String) ite.next();
		    output( filename, prop.toLowerCase(), map.get( prop ) );
		}
		output( filename, "pages", pdf.getNumberOfPages() );
		PdfReaderContentParser parser = new PdfReaderContentParser( pdf );
        for (int i = 1; i <= pdf.getNumberOfPages(); i++) {
		    output( filename, "page"+i, "pagesize", pdf.getPageSize( i ) );
		    PdfImageCheckRender listener = new PdfImageCheckRender( filename, i, pdf.getPageSize(i) );
	        parser.processContent(i, listener);
		    output( filename, "page"+i, "text length", listener.getResultantText().length() );
		    
		    ArrayList list = pdf.getLinks(i);

		    if (null != list) {
		    	int linkCount = list.size();
		    	if (linkCount > 0) {
		    		output( filename, "page"+i, "link数:", linkCount );
		    	} else {
		    		output( filename, "page"+i, "link数:", 0 );
		    	}
		    } else {
		    	output( filename, "page"+i, "link数:", 0 );
		    }
		    
            PdfArray asArray = pdf.getPageN(i).getAsArray(PdfName.ANNOTS);
            if (asArray != null) {
                for (PdfName name : asArray.getAsDict(0).getKeys()) {
                	output( filename, name + ":" + asArray.getAsDict(0).get(name), asArray.getAsDict(0).get(name).getBytes());
                }
                ListIterator<PdfObject> iterator = asArray.listIterator();
                while (iterator.hasNext()) {
                    PdfObject obj = iterator.next();
                    output( filename, obj + "| type:" + obj.type() + " |" + obj.getBytes() + "| ref:" + obj.getIndRef());
                }
            }
        }
	}
    
	//ファイルのサイズの取得
    static public float getFileSizes(PdfReader pdf) {
    	if (null == pdf) {
    		return 0f;
    	}
    	float l = pdf.getFileLength();
    	float size = l / 1024 / 1024;

    	return size;
    }

    static void output( String filename, String name, Object value ) {
		StringBuffer buf = new StringBuffer();
		if ( filename != null ) {
		    buf.append( filename + "\t" );
		}
		buf.append( name + "\t" + value );
		System.out.println( buf );
    }
    
    public static void output( String filename, String name, char value ) {
    	output( filename, name, String.valueOf( value ) );
    }
    
    public static void output( String filename, String name, int value ) {
    	output( filename, name, String.valueOf( value ) );
    }
    
    public static void output( String filename, String name, long value ) {
    	output( filename, name, String.valueOf( value ) );
    }
    
    public static void output( String filename, String name, float value ) {
    	output( filename, name, String.valueOf( value ) );
    }
    
    public static void output( String filename, String name, boolean value ) {
    	output( filename, name, String.valueOf( value ) );
    }
    
    public static void output( String filename, String name1, String name2, Object value ) {
    	output( filename, name1 + "\t" + name2, value );
    }
    
    public static void output( String filename, String name1, String name2, int value ) {
    	output( filename, name1 + "\t" + name2, value );
    }
    
    public static void output( String filename, String name1, String name2, long value ) {
    	output( filename, name1 + "\t" + name2, value );
    }
    
    public static void output( String filename, String name1, String name2, float value ) {
    	output( filename, name1 + "\t" + name2, value );
    }
    
    public static void output( String filename, String name1) {
    	output( filename, name1, "");
    }
}
